package com.trippin.servlets;

import java.io.BufferedReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityNotFoundException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.trippin.DB.DBHandler;
import com.trippin.DB.entities.AttractionEntity;
import com.trippin.DB.entities.Comment;
import com.trippin.DB.entities.ScheduledAttractionEntity;
import com.trippin.Utils.ServletUtil;
import com.trippin.Utils.ServletUtilConstants;


@SuppressWarnings("serial")
public class AttractionServlet extends HttpServlet {

	private static final Logger logger = Logger.getLogger(AttractionServlet.class.getCanonicalName());
	
	private static DBHandler dbHandlerInstance = DBHandler.INSTANCE;

	@Override
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		Action action = ServletUtil.getActionFromHeader(req,resp,AttractionServlet.class.toString());		
		long userId  = ServletUtil.getLongFromHeader(req, resp, ServletUtilConstants.USER_ID,
				AttractionServlet.class.toString(), action.getName());
		long attId = -1;
		long tripId = -1;

		switch(action) {
		case ATTEND_TO_ATTRACTION:
		case UNATTEND_FROM_ATTRACTION:
			tripId = ServletUtil.getLongFromHeader(req, resp, ServletUtilConstants.TRIP_ID,
					TripServlet.class.toString(), action.getName());
		case GET_ATTRACTION_BY_ID:
		case GET_SCHEDULE_ATTRACTIONS:
		case ADD_PLUS_TO_ATTRACTION:
		case ADD_MINUS_TO_ATTRACTION:
		case ADD_COMMENT_TO_ATTRACTION:
		case REMOVE_COMMENT_FROM_ATTRACTION:	
		case UPDATE_ATTRACTION:
		case DELETE_ATTRACTION:
		case GET_SCHEDULE_OF_ATTRACTION:
			attId = ServletUtil.getLongFromHeader(req, resp, ServletUtilConstants.ATTRACTION_ID,
					AttractionServlet.class.toString(), action.getName());
			break;
		}

		try {
			String bodyResponse = "";
			switch(action) {
			case GET_ATTRACTION_BY_ID:
				bodyResponse = getAttractionById(userId,attId);
				break;

			case GET_ATTRACTION_BY_NAME:
				bodyResponse = getAttractionByName(userId,req);
				break;

			case GET_SCHEDULE_ATTRACTIONS:
				bodyResponse = getScheduleAttractions(userId,attId,req);			
				break;

			case ATTEND_TO_ATTRACTION:
				bodyResponse = attendToAttraction(userId, tripId, attId);
				break;
				
			case UNATTEND_FROM_ATTRACTION:
				bodyResponse = unAttendFromAttraction(userId, tripId, attId);
				break;

			case CREATE_ATTRACTION:
				bodyResponse = createOrUpdateAttraction(userId, -1, req, resp, action);
				break;

			case UPDATE_ATTRACTION:
				bodyResponse = createOrUpdateAttraction(userId, attId, req, resp, action);
				if(bodyResponse == null) {
					ServletUtil.printError(resp, action.getName(), AttractionServlet.class.getName(),ServletUtilConstants.ERROR_ID_DONT_MATCH);
					return;
				}
				break;

			case DELETE_ATTRACTION:
				dbHandlerInstance.deleteAttraction(userId,attId);
				break;
				
			case ADD_COMMENT_TO_ATTRACTION:
				bodyResponse = addComment(userId, attId, req);
				break;
				
			case REMOVE_COMMENT_FROM_ATTRACTION:
				long commentId = ServletUtil.getLongFromHeader(req, resp, ServletUtilConstants.COMMENT_ID,
						AttractionServlet.class.toString(), action.getName());
				dbHandlerInstance.removeCommentFromAttraction(userId, attId, commentId);
				
			case ADD_PLUS_TO_ATTRACTION:
				bodyResponse = addPlusOrMinus(userId, attId, true);
				break;
				
			case ADD_MINUS_TO_ATTRACTION:
				bodyResponse = addPlusOrMinus(userId, attId, false);
				break;
								
			case GET_SCHEDULE_OF_ATTRACTION:
				bodyResponse = getScheduleOfAttraction(userId, attId, req, resp, action.getName());
				break;
								
			default:
				ServletUtil.printError(resp, action.getName(), AttractionServlet.class.getName(), ServletUtilConstants.ERROR_WRONG_ACTION_NAME);
				return;
			}

			ServletUtil.createResponse(resp, action.getName(), bodyResponse);


		} catch(Exception e) {
			ServletUtil.printError(resp,action.getName(), AttractionServlet.class.getName(), e.getMessage());
			logger.log(Level.SEVERE,e.toString(), e);
		}
	}

	
	private String getScheduleOfAttraction(long userId, long attId,
			HttpServletRequest req, HttpServletResponse resp, String actionName) throws IOException {
		Date start = null;
		Date end = null;
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
			String dateString = req.getHeader(ServletUtilConstants.START_TIME).trim();
			start = sdf.parse(dateString);
			dateString = req.getHeader(ServletUtilConstants.END_TIME).trim();
			end = sdf.parse(dateString);

		} catch(Exception e){
			ServletUtil.printError(resp, actionName ,AttractionServlet.class.getName(), ServletUtilConstants.ERROR_MISSING_DATES);
		}
		
		Iterable<ScheduledAttractionEntity> scheduleAttracrions = null;
		if((start != null) && (end != null)) {
			scheduleAttracrions = dbHandlerInstance.getScheduleOfAttraction(userId, attId, start, end);
		}
		else {
			scheduleAttracrions = new ArrayList<ScheduledAttractionEntity>();
		}
		
		return ServletUtil.getResponseBody(scheduleAttracrions);		
	}


	private String addPlusOrMinus(long userId, long attId, boolean addPlus) {
		 AttractionEntity att = dbHandlerInstance.addPlusOrMinusToAttraction(userId, attId, addPlus);
		return ServletUtil.getResponseBody(att);
	}


	private String addComment(long userId, long attId, HttpServletRequest req) throws IOException {
		
		BufferedReader in = req.getReader();
		String reqBodyString = ServletUtil.getRequestBody(in);
		in.close();

		Comment comment = (Comment)ServletUtil.getFromJSON(reqBodyString, Comment.class);
		 AttractionEntity att = dbHandlerInstance.addCommentToAttraction(userId, attId, comment);
		return ServletUtil.getResponseBody(att);
	}

	private String unAttendFromAttraction(long userId, long tripId, long attId) throws IOException {
		AttractionEntity attraction = dbHandlerInstance.unAttendFromAttraction(userId,tripId,attId);
		return ServletUtil.getResponseBody(attraction);
	}

	private String attendToAttraction(long userId, long tripId, long attId) throws EntityNotFoundException, IOException {
		AttractionEntity attraction = dbHandlerInstance.attendToAttraction(userId,tripId,attId);
		return ServletUtil.getResponseBody(attraction);
	}

	private String createOrUpdateAttraction(long userId, long attId, 
			HttpServletRequest req, HttpServletResponse resp, Action action) throws IOException, EntityNotFoundException, ServletException {
		BufferedReader in = req.getReader();
		String reqBodyString = ServletUtil.getRequestBody(in);
		in.close();

		AttractionEntity attraction = (AttractionEntity)ServletUtil.getFromJSON(reqBodyString, AttractionEntity.class);
		AttractionEntity att = null;
		if(action == Action.CREATE_ATTRACTION) {
			String[] requireds = {ServletUtilConstants.REQUIRED_LATITUDE, ServletUtilConstants.REQUIRED_LONGITUDE};
			ServletUtil.checkRequiredFields(reqBodyString,requireds, resp, action.getName(), AttractionServlet.class.getName());
			att = dbHandlerInstance.createNewAttraction(userId, attraction);
		}
		else {
			//String[] requireds = {ServletUtilConstants.REQUIRED_ID, ServletUtilConstants.REQUIRED_LATITUDE, 
			//		ServletUtilConstants.REQUIRED_LONGITUDE};
			//ServletUtil.checkRequiredFields(reqBodyString,requireds, resp, action.getName(), LocationServlet.class.getName());
			att = dbHandlerInstance.updateAttraction(userId, attId, attraction);
			if(att == null) {
				return null;
			}
		}
		return ServletUtil.getResponseBody(att);
	}


	private String getAttractionById(long userId, long attrId) throws EntityNotFoundException {
		AttractionEntity attraction = dbHandlerInstance.getAttractionById(userId,attrId);
		return ServletUtil.getResponseBody(attraction);
	}


	private String getAttractionByName(long userId, HttpServletRequest req) throws EntityNotFoundException, IOException {
		Iterable<AttractionEntity> attractions = null;
		String atrName = req.getHeader(ServletUtilConstants.ATTRACTION_NAME);
		attractions = dbHandlerInstance.getAttractionsContains(atrName);
		return ServletUtil.getResponseBody(attractions);
	}


	private String getScheduleAttractions(long userId, long attrId, 
			HttpServletRequest req) throws EntityNotFoundException, IOException {

		Date startTime = ServletUtil.getDateTime(req,ServletUtilConstants.START_TIME);
		Date endTime = ServletUtil.getDateTime(req,ServletUtilConstants.END_TIME);

		Iterable<ScheduledAttractionEntity> scheduleAttractions = 
				dbHandlerInstance.getScheduleOfAttraction(userId,attrId,startTime, endTime);
		return ServletUtil.getResponseBody(scheduleAttractions);		

	}


}
